/** 
 * 游戏控制类
 * 游戏核心
 */
import Player from "./Player";
import Poker from "./Poker";

class Game {
	constructor() {
		console.log('Game类被实例化');
		this.testModel = false; //测试模式 三个AI自动打牌
		this.playerList = []; //玩家数组
		this.pokerList = []; //牌数组
		this.dizhuPokerList = []; //地主牌（3张）
		this.deskPokerObj = null; //当前已出牌信息
		this.oldPokerList = []; //历史出牌信息（不包含当前已出的）
		this.currentPlayer = null; //准备出牌的玩家
		this.currentJiaoFenPlayer = null; //准备叫分的玩家
		this.jiaoFenCount = 0; //叫分统计
		this.dizhu = null; //地主
		this.MaxSecond = 100; //出牌等待时间（秒）
		this.second = this.MaxSecond;
		this.BaseScore = 1; //每局底分
		this.score = this.BaseScore; //当前局分
		this.stage = 'ready'; //阶段 ready准备\jiaoFen叫分\play游戏中
		this.init();
	}

	/** 
	 * 初始化
	 */
	init() {
		this.initPokerList();
		this.initPlayerList();
	}

	/** 
	 * 初始化牌面
	 * 3-15有花色（type）
	 * 16 17大小王没有花色
	 */
	initPokerList() {
		this.pokerList = [];
		for (let number = 3; number <= 15; number++) {
			for (let type = 0; type < 4; type++) {
				let poker = new Poker({
					number: number,
					type: type,
				});
				this.pokerList.push(poker);
			}
		}
		for (let number = 16; number <= 17; number++) {
			let poker = new Poker({
				number: number,
			});
			this.pokerList.push(poker);
		}
	}

	/** 
	 * 初始化玩家
	 * 初始化后并指定每个玩家的上家和下家
	 */
	initPlayerList() {
		let that = this;
		this.playerList = [];
		let player0 = new Player({
			name: '我',
			isRobot: that.testModel,
			game: this,
		});
		let player1 = new Player({
			name: '机器1',
			isRobot: true,
			game: this,
		});
		let player2 = new Player({
			name: '机器2',
			isRobot: true,
			game: this,
		});
		this.playerList = [player0, player1, player2];

		this.playerList[0].next = this.playerList[1];//下家
		this.playerList[1].next = this.playerList[2];
		this.playerList[2].next = this.playerList[0];
		this.playerList[0].last = this.playerList[2];//上家
		this.playerList[1].last = this.playerList[0];
		this.playerList[2].last = this.playerList[1];

	}

	/**
	 * 人类玩家准备，发牌，开始叫分
	 */
	setReady() {
		if (this.playerList[0] && this.playerList[0].ready && this.playerList[1] && this.playerList[1].ready && this
			.playerList[2] && this.playerList[2].ready) {
			this.sendPoker();
			this.startJiaoFen();
		}
	}

	/**
	 * 叫分
	 */
	startJiaoFen() {
		this.stage = 'jiaoFen';
		let index = this.getRandomIntInclusive(0, 2);
		this.currentJiaoFenPlayer = this.playerList[index];
	}

	/**
	 * 叫分并判断地主
	 */
	someOneJiaoFen() {
		let that = this;
		this.jiaoFenCount++;

		let timeWait = 1000;
		if (that.testModel) {
			timeWait = 0;
		}

		if (this.jiaoFenCount === 3) {
			setTimeout(function() {
				that.setDiZhu();
			}, timeWait);
			return;
		} else {
			this.currentJiaoFenPlayer = this.currentJiaoFenPlayer.next;
		}
	}

	/**
	 * 设置地主
	 * 1，分值最大的当选地主
	 * 2，分值相同时随机一个地主
	 * 3，设置地主牌
	 * 4，游戏开始
	 */
	setDiZhu() {
		let sortList = this.playerList.slice(0).sort(this.sortByJiaoFen);
		let dizhu;
		if (sortList[0].jiaoFen === sortList[1].jiaoFen) {
			if (sortList[0].jiaoFen === sortList[2].jiaoFen) {
				let index = this.getRandomIntInclusive(0, 2);
				dizhu = sortList[index];
			} else {
				let index = this.getRandomIntInclusive(0, 1);
				dizhu = sortList[index];
			}
		} else {
			dizhu = sortList[0];
		}

		dizhu.type = 'dizhu';
		this.dizhu = dizhu;

		this.sendDiZhuPoker();
		this.start();
	}

	/**
	 * 叫分排序
	 * @param {Object} a
	 * @param {Object} b
	 */
	sortByJiaoFen(a, b) {
		return b.jiaoFen - a.jiaoFen;
	}

	/**
	 * 重置出牌时间
	 */
	resetTime() {
		this.second = this.MaxSecond;
	}

	/**
	 * 出牌计时
	 */
	timeLoop() {
		if (this.stage !== 'play') {
			return;
		}
		this.second--;

		if (this.second === 0) {
			this.timeout();
		}

		let that = this;
		setTimeout(function() {
			that.timeLoop();
		}, 1000);
	}

	/**
	 * 超过出牌时间算pass
	 */
	timeout() {
		this.currentPlayer.playByString('pass');
	}

	/**
	 * 开始游戏
	 */
	start() {
		this.stage = 'play'; //切换舞台属性
		this.timeLoop(); //计时
		this.currentPlayer = this.dizhu; //地主首先出牌
		if (this.currentPlayer.isRobot) { //地主是机器人时调用ai
			this.currentPlayer.playByAI();
		}
	}

	/**
	 * 游戏结束，重置并发牌
	 */
	reset() {
		this.playerList[0].reset();
		this.playerList[1].reset();
		this.playerList[2].reset();
		this.pokerList = [];
		this.dizhuPokerList = [];
		this.deskPokerObj = null;
		this.oldPokerList = [];
		this.currentPlayer = null;
		this.currentJiaoFenPlayer = null;
		this.jiaoFenCount = 0;
		this.dizhu = null;
		this.second = this.MaxSecond;
		this.score = this.BaseScore;
		this.stage = 'ready';
		this.initPokerList();
	}

	/**
	 * 玩家出牌
	 * 
	 * @param {Object} obj 出牌相关信息
	 */
	someOneSendPoker(obj) {
		this.clearDesk(); //清除桌面牌
		this.deskPokerObj = obj; //当前出牌放入桌面牌类
		this.checkBoom(obj); //炸弹记分

		let over = this.checkGameOver();
		if (over) {
			this.gameOver();
			return;
		}

		this.next(); //下家出牌
	}

	/**
	 * 炸弹分数翻1番 火箭翻2番
	 * 
	 * @param {Object} obj 出牌信息
	 */
	checkBoom(obj) {
		if (obj.type === 'four') {
			this.score *= 2;
		} else if (obj.type === 'four') {
			this.score *= 4;
		}
	}

	/**
	 * 下家出牌
	 */
	next() {
		this.resetTime();
		this.currentPlayer = this.currentPlayer.next;
		if (this.currentPlayer.isRobot) {
			this.currentPlayer.playByAI();
		}
	}

	/**
	 * 游戏结束
	 * 1，全ai模式控制台打印金币
	 * 2，人类玩家模式弹出提示
	 * 3，更新金币，重置游戏
	 */
	gameOver() {
		if (!this.testModel) {
			alert('游戏结束! ' + this.currentPlayer.name + ' [' + this.currentPlayer.type + '] 胜!');
		} else {
			console.log(this.playerList[0].money + ' ' + this.playerList[1].money + ' ' + this.playerList[2].money +
				' ');
		}
		this.settleMoney();
		this.reset();
	}

	/**
	 * 金币结算
	 */
	settleMoney() {
		if (this.currentPlayer.type === 'nongmin') {
			this.currentPlayer.money += this.score;

			if (this.currentPlayer.next.type === 'nongmin') {
				this.currentPlayer.next.money += this.score;
			} else {
				this.currentPlayer.next.money -= this.score * 2;
			}

			if (this.currentPlayer.last.type === 'nongmin') {
				this.currentPlayer.last.money += this.score;
			} else {
				this.currentPlayer.last.money -= this.score * 2;
			}

		} else {
			this.currentPlayer.money += this.score * 2;
			this.currentPlayer.next.money -= this.score;
			this.currentPlayer.last.money -= this.score;
		}

	}

	/**
	 * 检查游戏是否结束
	 * 无手牌时，游戏结束
	 */
	checkGameOver() {
		if (this.currentPlayer.pokerList.length === 0) {
			return true;
		}
	}

	/**
	 * 清空桌面牌
	 */
	clearDesk() {
		if (this.deskPokerObj) {
			this.oldPokerList.push(this.deskPokerObj);
			this.deskPokerObj = null;
		}
	}

	/**
	 * 给地主发地主牌，排序
	 */
	sendDiZhuPoker() {
		do {
			let poker = this.pokerList.splice(0, 1)[0];
			this.dizhu.addPoker(poker);
		} while (this.pokerList.length > 0);

		this.dizhu.sortPoker();
	}

	/**
	 * 发牌
	 * 每人17张
	 */
	sendPoker() {
		let player = this.playerList[0];
		do {
			let index = this.getRandomIntInclusive(0, this.pokerList.length - 1);
			let poker = this.pokerList.splice(index, 1)[0];
			player.addPoker(poker);
			player = player.next;
		} while (this.pokerList.length > 3);

		for (let i = 0; i < this.playerList.length; i++) {
			this.playerList[i].sortPoker();
		}

		this.dizhuPokerList = this.pokerList.slice(0);
	}

	/**
	 * @param {Object} min
	 * @param {Object} max
	 * 获取随机数，用于随机发牌
	 */
	getRandomIntInclusive(min, max) {
		return Math.floor(Math.random() * (max - min + 1)) + min;
	}
}

export default Game;
